package com.wx.core.process.message.event;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.wx.commons.ResultConstant;
import com.wx.core.process.BaseProcess;
import com.wx.core.process.BaseResult;
import com.wx.core.process.MsgXmlUtil;
import com.wx.core.process.ProcessResult;
import com.wx.core.process.WxApi;
import com.wx.core.process.WxServiceProcess;
import com.wx.core.vo.Image;
import com.wx.core.vo.MsgNews;
import com.wx.core.vo.MsgRequest;
import com.wx.core.vo.MsgResponseImage;
import com.wx.core.vo.MsgResponseNews;
import com.wx.core.vo.MsgResponseText;
import com.wx.core.vo.MsgResponseVoice;
import com.wx.core.vo.MsgText;
import com.wx.core.vo.response.Fans;
import com.wx.entity.SysWxAutoReply;
import com.wx.entity.SysWxAutoReplyExample;
import com.wx.entity.SysWxuser;
import com.wx.entity.WxFansUser;
import com.wx.entity.WxImageReply;
import com.wx.entity.WxMulReply;
import com.wx.entity.WxPicReply;
import com.wx.entity.WxResource;
import com.wx.entity.WxResourceExample;
import com.wx.entity.WxTextReply;
import com.wx.entity.WxVoiceReply;
import com.wx.flag.KeyWordType;
import com.wx.service.SysWxAutoReplyService;
import com.wx.service.SysWxTokenService;
import com.wx.service.SysWxuserService;
import com.wx.service.WxFansUserService;
import com.wx.service.WxImageReplyService;
import com.wx.service.WxMulReplyService;
import com.wx.service.WxPicReplyService;
import com.wx.service.WxResourceService;
import com.wx.service.WxTextReplyService;
import com.wx.service.WxVoiceReplyService;
import com.wx.util.JsonUtil;
import com.wx.util.StringUtils;
import com.zyht.bank.entity.AxdCustInfo;
import com.zyht.bank.entity.AxdCustInfoExample;
import com.zyht.bank.service.AxdCustInfoService;
import com.zyht.common.bean.ThreadPoolWrapperBean;
import com.zyht.common.inf.Observable;
import com.zyht.common.inf.Observer;
import com.zyht.common.util.HttpUtils;
import com.zyht.common.util.SpecialCharacterFilterUtil;

/**
 * @desc 关注或取消关注时的流程处理
 * @author gavin
 * @date 2014-12-9
 * @time 上午11:09:35
 * @version 1.0
 */
public class SubscribeEventProcess extends BaseProcess implements Observable {

	Logger logger = LoggerFactory.getLogger(getClass());

	@Resource
	private SysWxAutoReplyService sysWxAutoReplyService;
	@Resource
	WxTextReplyService wxTextReplyService;
	@Resource
	WxImageReplyService wxImageReplyService;
	@Resource
	WxPicReplyService wxPicReplyService;
	@Resource
	WxMulReplyService wxMulReplyService;
	@Resource
	WxVoiceReplyService wxVoiceReplyService;
	@Resource
	WxResourceService wxResourceService;

	@Resource
	private AxdCustInfoService axdCustInfoService;
	@Resource
	private SysWxTokenService sysWxTokenService;
	@Resource
	private SysWxuserService sysWxuserService;
	@Resource
	private WxFansUserService wxFansUserService;

	private volatile boolean isFirstRequset = true;

	private String serverAblolutlyPath;

	private String AXD_ORG_CODE = "axd_org_";
	// 观察者
	private List<Observer> observerList = new ArrayList<Observer>();

	/**
	 * 订阅的服务
	 */
	@Override
	public BaseResult process(HttpServletRequest req, HttpServletResponse res, MsgRequest msgReq) {
		if (isFirstRequset) {
			serverAblolutlyPath = getAbsolutPath(req);
			isFirstRequset = false;
		}
		return subscribeWenXin(msgReq);
	}

	/**
	 * @author: gavin @date: 2015年7月13日 @Title: subscribeWenXin @Description:
	 *          关注时信息录入库中 @param @param msgReq @param @return 设定文件 @return int
	 *          返回类型 @throws
	 */
	private ProcessResult subscribeWenXin(MsgRequest msgRequest) {
		ProcessResult result = new ProcessResult();

		String openid = msgRequest.getFromUserName();
		String wxid = msgRequest.getToUserName();

		SysWxuser user = sysWxuserService.selectByWxid(wxid);
		final String token = sysWxTokenService.getAccessToken(wxid, user.getAppid(), user.getAppsecretd());
		// 新启线程 写入粉丝
		Runnable run = () -> {
			// 写入粉丝信息,先查询是否存在
			WxFansUser wxFansUser = wxFansUserService.selectByOpenId(openid);
			if (wxFansUser == null) {
				String requestUrl = WxApi.getFansInfoUrl(token, openid);
				String responseStr = HttpUtils.httpsGet(requestUrl);
				JSONObject jSONObject = JSONObject.parseObject(responseStr);
				Fans fans = (Fans) JsonUtil.str2bean(jSONObject.toString(), Fans.class);
				WxFansUser wxfan = new WxFansUser();
				BeanUtils.copyProperties(fans, wxfan);
				wxfan.setNickname(SpecialCharacterFilterUtil.utf8ToUnicode(fans.getNickname()));
				wxfan.setWxid(wxid);
				wxfan.setSubscribeTime(new Date());
				wxFansUserService.insert(wxfan);
				// 处理用户绑定状态
				try {
					String qrscene = msgRequest.getEventKey();
					AxdCustInfo cust = new AxdCustInfo();
					if (qrscene != null && qrscene.startsWith("qrscene_")) {
						String orgCode = qrscene.replace("qrscene_", "");
						if (orgCode.startsWith(AXD_ORG_CODE)) {
							orgCode = orgCode.replace(AXD_ORG_CODE, "");
							cust.setLoanOrgCode(orgCode);
						}

					}
					cust.setCreateTime(new Date());
					cust.setFanUserId(wxfan.getId());
					cust.setBandingStatus("0");
					cust.setOpenid(openid);
					axdCustInfoService.addOne(cust);
				} catch (Exception e) {
					e.printStackTrace();
				}

			} else {// 更新成关注状态，再次关注
				wxFansUser.setSubscribe(1);
				wxFansUserService.updateByPrimaryKey(wxFansUser);
				// 处理用户绑定状态
				AxdCustInfoExample example = new AxdCustInfoExample();
				example.createCriteria().andFanUserIdEqualTo(wxFansUser.getId());
				List<AxdCustInfo> list = axdCustInfoService.list(example);
				if (list.size() > 0) {
					AxdCustInfo axdCustInfo = list.get(0);
					String qrscene = msgRequest.getEventKey();
					AxdCustInfo cust = new AxdCustInfo();
					if (qrscene != null && qrscene.startsWith("qrscene_")) {
						String orgCode = qrscene.replace("qrscene_", "");
						if (orgCode.startsWith(AXD_ORG_CODE)) {
							orgCode = orgCode.replace(AXD_ORG_CODE, "");
							if (StringUtils.isEmpty(axdCustInfo.getLoanOrgCode()))
								cust.setLoanOrgCode(orgCode);
						}

					}

					axdCustInfo.setOpenid(openid);
					axdCustInfo.setCreateTime(new Date());
					axdCustInfoService.updateById(axdCustInfo);

				}
			}

		};

		ThreadPoolWrapperBean.getThreadPool().putThread(run);

		SysWxAutoReplyExample sysWxAutoReplyExample = new SysWxAutoReplyExample();
		sysWxAutoReplyExample.createCriteria().andWxidEqualTo(wxid);
		PageHelper.startPage(1, 1);
		List<SysWxAutoReply> sysWxAutoReplyList = sysWxAutoReplyService.selectByExample(sysWxAutoReplyExample);
		if (sysWxAutoReplyList.size() > 0) {
			SysWxAutoReply auto = sysWxAutoReplyList.get(0);
			int msgType = auto.getIsMultipart();
			if (msgType == 0) {
				MsgText msgText = new MsgText();
				msgText.setContent(StringEscapeUtils.unescapeJava(auto.getContent()));
				MsgResponseText msgResponseText = WxServiceProcess.getMsgResponseText(msgRequest, msgText);
				String xml = MsgXmlUtil.textToXml(msgResponseText);
				result.setResult(xml);
			}

			if (KeyWordType.TYPE_TXT.equals(msgType)) {
				// 文本回复
				WxTextReply wxTextReply = wxTextReplyService.selectByPrimaryKey(auto.getPicReplyId());
				getTextReply(result, wxTextReply, msgRequest);
			} else if (KeyWordType.TYPE_PIC.equals(msgType)) {
				// 单图文回复
				WxPicReply wxPicReply = wxPicReplyService.selectByPrimaryKey(auto.getPicReplyId());
				getPicReply(result, wxPicReply, msgRequest);
			} else if (KeyWordType.TYPE_MUL_PIC.equals(msgType)) {
				// 多图文回复
				WxMulReply wxMulReply = wxMulReplyService.selectByPrimaryKey(auto.getPicReplyId());
				getMulPicReply(result, wxMulReply, msgRequest);
			} else if (KeyWordType.TYPE_RADIO.equals(msgType)) {
				// 音频回复
				WxVoiceReply wxVoiceReply = wxVoiceReplyService.selectByPrimaryKey(auto.getPicReplyId());
				getVoiceReply(result, wxVoiceReply, msgRequest);
			} else if (KeyWordType.TYPE_IMAGE.equals(msgType)) {
				// 图片回复
				WxImageReply wxImageReply = wxImageReplyService.findOneById(auto.getPicReplyId());
				getImageReply(result, wxImageReply, msgRequest);
			}
		}

		Map<String, Object> params = new HashMap<String, Object>();
		params.put("wxid", wxid);
		params.put("openid", openid);
		params.put("serverAblolutlyPath", serverAblolutlyPath);
		params.put("token", token);

		notifyObservers(params);

		return result;
	}

	/**
	 * @author: gavin @date: 2015年7月15日 @Title: getTextReply @Description:
	 *          获取关键词文本回复 @param @param msgRequest @param @return 设定文件 @return
	 *          ProcessResult 返回类型 @throws
	 */
	private ProcessResult getTextReply(ProcessResult result, WxTextReply wxTextReply, MsgRequest msgReq) {
		try {
			// 组装发送消息
			MsgText msgText = new MsgText();
			msgText.setContent(wxTextReply.getContent());
			MsgResponseText msgResponseText = WxServiceProcess.getMsgResponseText(msgReq, msgText);
			String xml = MsgXmlUtil.textToXml(msgResponseText);
			result.setResult(xml);
		} catch (Exception e) {
			e.printStackTrace();
			result.setCode(ResultConstant.FAILUER);
			result.setErrmsg(e.getMessage());
		}
		result.setCode(ResultConstant.SUCCESS);
		return result;
	}

	/**
	 * @author: gavin @date: 2015年7月15日 @Title: getTextReply @Description:
	 *          获取关键词单图文回复 @param @param msgRequest @param @return 设定文件 @return
	 *          ProcessResult 返回类型 @throws
	 */
	private ProcessResult getPicReply(ProcessResult result, WxPicReply wxPicReply, MsgRequest msgRequest) {
		try {
			// 获取关键词信息
			List<WxPicReply> wxPicReplyList = new ArrayList<WxPicReply>();
			wxPicReplyList.add(wxPicReply);
			// 组装发送消息
			if (wxPicReplyList != null && wxPicReplyList.size() > 0) {
				String xml = getResponseNews(result, msgRequest, wxPicReplyList);
				result.setResult(xml);
			}
		} catch (Exception e) {
			e.printStackTrace();
			result.setCode(ResultConstant.FAILUER);
			result.setErrmsg(e.getMessage());
		}
		result.setCode(ResultConstant.SUCCESS);
		return result;
	}

	private ProcessResult getImageReply(ProcessResult result, WxImageReply wxImageReply, MsgRequest msgRequest) {
		try {
			WxResourceExample wxResourceExample = new WxResourceExample();
			wxResourceExample.createCriteria().andRefTypeEqualTo(KeyWordType.TYPE_IMAGE.getValue())
					.andRefIdEqualTo(wxImageReply.getId());
			PageHelper.startPage(1, 1);
			List<WxResource> wxResourceList = wxResourceService.selectByExample(wxResourceExample);
			if (wxResourceList == null || wxResourceList.size() == 0)
				return null;
			String mediaId = wxResourceList.get(0).getMediaId();
			Image image = new Image();
			image.setMediaId(mediaId);
			// 组装发送消息
			MsgResponseImage msgResponseImage = WxServiceProcess.getMsgResponseImage(msgRequest, image);
			String xml = MsgXmlUtil.imageToXml(msgResponseImage);
			result.setResult(xml);
		} catch (Exception e) {
			e.printStackTrace();
			result.setCode(ResultConstant.FAILUER);
			result.setErrmsg(e.getMessage());
		}
		result.setCode(ResultConstant.SUCCESS);
		return result;
	}

	/**
	 * @author: gavin @date: 2015年7月15日 @Title: getTextReply @Description:
	 *          获取关键词单图文回复 @param @param msgRequest @param @return 设定文件 @return
	 *          ProcessResult 返回类型 @throws
	 */
	private ProcessResult getMulPicReply(ProcessResult result, WxMulReply wxMulReply, MsgRequest msgRequest) {
		try {
			// 获取关键词信息
			List<WxPicReply> wxPicReplyList = new ArrayList<WxPicReply>();
			String ids = wxMulReply.getPicIds();
			if (StringUtils.isEmpty(ids))
				return null;
			String[] arr = ids.split(",");
			if (arr == null || arr.length == 0)
				return null;
			for (String str : arr) {
				if (!StringUtils.isEmpty(str.trim())) {
					WxPicReply wxPicReply = wxPicReplyService.selectByPrimaryKey(Integer.valueOf(str));
					wxPicReplyList.add(wxPicReply);
				}
			}

			// 组装发送消息
			if (wxPicReplyList != null && wxPicReplyList.size() > 0) {
				String xml = getResponseNews(result, msgRequest, wxPicReplyList);
				result.setResult(xml);
			}
		} catch (Exception e) {
			e.printStackTrace();
			result.setCode(ResultConstant.FAILUER);
			result.setErrmsg(e.getMessage());
		}
		result.setCode(ResultConstant.SUCCESS);
		return result;
	}

	/**
	 * @author: gavin @date: 2015年7月15日 @Title: getResponseNews @Description:
	 *          获取消息 @param @return 设定文件 @return MsgResponseNews 返回类型 @throws
	 */
	private String getResponseNews(ProcessResult result, MsgRequest msgRequest, List<WxPicReply> wxPicReplyList) {
		List<MsgNews> msgNewsList = new ArrayList<MsgNews>();
		wxPicReplyList.forEach(p -> {
			MsgNews msgNews = new MsgNews();
			msgNews.setTitle(p.getTitle());
			msgNews.setPicpath(serverAblolutlyPath + p.getpImgHref());
			msgNews.setUrl(serverAblolutlyPath + "/pic/detail?id=" + p.getId());
			msgNews.setFromurl(p.getArticleUrl());
			msgNews.setBrief(p.getpSummary());
			msgNewsList.add(msgNews);
		});
		MsgResponseNews msgResPonseNews = WxServiceProcess.getMsgResponseNews(msgRequest, msgNewsList);
		return MsgXmlUtil.newsToXml(msgResPonseNews);
	}

	/**
	 * @author：Gavin 2015年7月23日 @Title: getVoiceReply @Description:
	 *               关键词语音回复 @param @param msgRequest @param @return
	 *               设定文件 @return ProcessResult 返回类型 @throws
	 */
	private ProcessResult getVoiceReply(ProcessResult result, WxVoiceReply wxVoiceReply, MsgRequest msgRequest) {
		try {
			WxResourceExample wxResourceExample = new WxResourceExample();
			wxResourceExample.createCriteria().andRefTypeEqualTo(KeyWordType.TYPE_RADIO.getValue())
					.andRefIdEqualTo(wxVoiceReply.getId());
			List<WxResource> wxResourceList = wxResourceService.selectByExample(wxResourceExample);
			if (wxResourceList == null || wxResourceList.size() == 0)
				return null;
			String mediaId = wxResourceList.get(0).getMediaId();

			MsgResponseVoice msgResponseVoice = WxServiceProcess.getMsgResponseVoice(msgRequest, mediaId);
			String xml = MsgXmlUtil.voiceToXml(msgResponseVoice);
			result.setResult(xml);
		} catch (Exception e) {
			e.printStackTrace();
			result.setCode(ResultConstant.FAILUER);
			result.setErrmsg(e.getMessage());
		}
		result.setCode(ResultConstant.SUCCESS);
		return result;
	}

	@Override
	public void notifyObservers(Object arg) {
		for (Observer o : observerList) {
			o.update(this, arg);
		}
	}

	public void setObservers(List<Observer> observers) {
		if (null != observers) {
			this.observerList.addAll(observers);
		}
	}
}